package org.vsg.security.model.service.impl;

import java.io.Serializable;
import java.util.Collection;
import java.util.Vector;

import org.vsg.common.biz.exception.ServiceException;
import org.vsg.common.pagination.Pagination;
import org.vsg.common.pagination.PaginationException;
import org.vsg.common.pagination.carrier.Carrier;
import org.vsg.common.pagination.carrier.RecordLimitCarrier;
import org.vsg.common.pagination.datatrans.PaginationProvider;
import org.vsg.common.pagination.datatrans.PaginationProviderFactory;
import org.vsg.security.model.domain.ResourceAssociation;
import org.vsg.security.model.domain.SysMenuResource;
import org.vsg.security.model.domain.SysOperation;
import org.vsg.security.model.domain.SysRole;
import org.vsg.security.model.persistence.ResourceAssociationDao;
import org.vsg.security.model.persistence.SysMenuResourceDao;
import org.vsg.security.model.persistence.SysOperationDao;
import org.vsg.security.model.persistence.SysRoleDao;
import org.vsg.security.model.service.SysMenuResourceService;
import org.vsg.security.model.vo.json.MenuResourceNodeWithChildrenVO;


public class SysMenuResourceServiceImpl implements SysMenuResourceService {
	/**
	 * set the pagination provider factory
	 * 
	 * 
	 */
	private PaginationProviderFactory factory = PaginationProviderFactory.getInstance();

	private SysMenuResourceDao sysMenuResourceDao;
	
	private SysOperationDao sysOperationDao;
	
	private SysRoleDao sysRoleDao;
	
	private ResourceAssociationDao resourceAssociationDao;

	/**
	 * @param carrier
	 * @return
	 * @exception ServiceException
	 * @exception PaginationException
	 */
	public Pagination pageSysMenuResource(Carrier carrier) throws ServiceException,
			PaginationException {
		// TODO: implement
		PaginationProvider provider = factory
				.generateProvider((RecordLimitCarrier) carrier);
		return sysMenuResourceDao.pageSysMenuResource(provider);
	}

	/**
	 * @param carrier
	 * @return
	 * @throws ServiceException
	 * @exception PaginationException
	 */
	public Pagination pageSysMenuResourceByAll(Carrier carrier) throws ServiceException,
			PaginationException {
		// TODO: implement
		PaginationProvider provider = factory
				.generateProvider((RecordLimitCarrier) carrier);
		return sysMenuResourceDao.pageSysMenuResourceByAll(provider);
	}
	
	@Override
	public void saveAll(Collection<SysMenuResource> all)
			throws ServiceException {
		// TODO Auto-generated method stub
		sysMenuResourceDao.saveAll(all);
		
	}  	

	/**
	 * @param sysMenuResource
	 * @exception ServiceException
	 */
	public void addSysMenuResource(SysMenuResource sysMenuResource) throws ServiceException {
		// TODO: implement
		sysMenuResourceDao.save(sysMenuResource);
	}

	/**
	 * @param sysMenuResource
	 * @exception ServiceException
	 */
	public void updateSysMenuResource(SysMenuResource sysMenuResource) throws ServiceException {
		// TODO: implement
		sysMenuResourceDao.update(sysMenuResource);
	}

	/**
	 * @param sysMenuResource
	 * @exception ServiceException
	 */
	public void updateSimpleSysMenuResource(SysMenuResource newEntity) throws ServiceException {
		// TODO: implement
		SysMenuResource original = sysMenuResourceDao.load( newEntity.getId() );
		
		original.setFlagStrategy( newEntity.getFlagStrategy()  );
		original.setFlagDisabled( newEntity.getFlagDisabled()  );
		original.setParentId( newEntity.getParentId()  );
		original.setName( newEntity.getName() );
		original.setCode( newEntity.getCode() );
		original.setDescription( newEntity.getDescription() );
		
		
		// --- update the method ---
		sysMenuResourceDao.update( original );		
		
	}

	/**
	 * @param sysMenuResource
	 * @exception ServiceException
	 */
	public void deleteSysMenuResource(SysMenuResource sysMenuResource) throws ServiceException {
		// TODO: implement
		sysMenuResourceDao.delete(sysMenuResource);
	}

	@Override
	public void deleteAll(Collection<SysMenuResource> all)
			throws ServiceException {
		// TODO Auto-generated method stub
		sysMenuResourceDao.deleteAll(all);
	}
	

	/**
	 * @param pk
	 * @exception ServiceException
	 */
	public SysMenuResource loadSysMenuResource(Serializable pk) throws ServiceException {
		// TODO: implement
		return sysMenuResourceDao.load(pk);
	}


	@Override
	public Collection<SysMenuResource> findByAll() throws ServiceException {
		// TODO Auto-generated method stub
		return sysMenuResourceDao.findByAll();
	}


	public SysMenuResourceDao getSysMenuResourceDao() {
		return sysMenuResourceDao;
	}

	/**
	 * @param newSysMenuResourceDao
	 */
	public void setSysMenuResourceDao(SysMenuResourceDao newSysMenuResourceDao) {
		sysMenuResourceDao = newSysMenuResourceDao;
	}

	@Override
	public Collection<MenuResourceNodeWithChildrenVO> findAllMenuResourceByRoot()
			throws ServiceException {
		// TODO Auto-generated method stub
		Collection<SysMenuResource> menus = this.sysMenuResourceDao.findRootMenuResource();
		
		Collection<MenuResourceNodeWithChildrenVO> allMenu = generateTreeByMenuReource(menus);
		
		return allMenu;
	}

	private Collection<MenuResourceNodeWithChildrenVO> generateTreeByMenuReource(Collection<SysMenuResource> moreMenuReource ) {
		
		MenuResourceNodeWithChildrenVO nodeVo = null;
		
		Collection<MenuResourceNodeWithChildrenVO> allNodeVo = new Vector<MenuResourceNodeWithChildrenVO>();
		
		for (SysMenuResource menuResource : moreMenuReource) {
			
			if (menuResource.getFlagDeleted() == 0 ) {
				
				nodeVo = new MenuResourceNodeWithChildrenVO();
				nodeVo.setMenuResource( menuResource );
				
				Collection<SysMenuResource> subChildren = this.sysMenuResourceDao.findChildrenResource(menuResource);
				
				if (subChildren.size() > 0) {
					nodeVo.setIfLeaf(false);
					Collection<MenuResourceNodeWithChildrenVO> children = generateTreeByMenuReource(subChildren);
					nodeVo.setChildren( children );
				} else {
					nodeVo.setIfLeaf(true);
				}
				
				
				allNodeVo.add(nodeVo);
			}
			
		}
		
		return allNodeVo;
	}

	
	@Override
	public void bindingMenuRoleAssociation(SysMenuResource menuResource,
			SysOperation operation, SysRole role) throws ServiceException {
		// TODO Auto-generated method stub
		SysMenuResource oMenuReso = this.sysMenuResourceDao.load( menuResource.getId() );
		
		Collection<SysOperation> oOperas = this.sysOperationDao.findByOperation( operation.getOperation() );
		SysOperation oOpera = oOperas.iterator().next();
		
		SysRole sysRole = this.sysRoleDao.load( role.getId() );
		
		Collection<ResourceAssociation> assoRelation = resourceAssociationDao.findAssocation(sysRole , menuResource);
		
		ResourceAssociation asso = null;
		
		if (assoRelation.isEmpty()) {
			asso = new ResourceAssociation();
			asso.setOperation(oOpera);
			asso.setRole(sysRole);
			asso.setResource(oMenuReso);
			resourceAssociationDao.save( asso );
		} else {
			asso = assoRelation.iterator().next();
			asso.setOperation(oOpera);
			resourceAssociationDao.update(asso);
		}
	}

	@Override
	public void removeMenus(long[] menuIds) throws ServiceException {
		// TODO Auto-generated method stub
		Collection<SysMenuResource> menuResourceColl = new Vector<SysMenuResource>();
		SysMenuResource resource = null;
		
		for (int i = 0 ; i < menuIds.length ; i++) {
			resource = this.sysMenuResourceDao.load( menuIds[i] );
			resource.setFlagDeleted( (short)1 );
			menuResourceColl.add( resource );
		}
		this.sysMenuResourceDao.saveAll( menuResourceColl );
		
	}

	public SysOperationDao getSysOperationDao() {
		return sysOperationDao;
	}

	public void setSysOperationDao(SysOperationDao sysOperationDao) {
		this.sysOperationDao = sysOperationDao;
	}

	public SysRoleDao getSysRoleDao() {
		return sysRoleDao;
	}

	public void setSysRoleDao(SysRoleDao sysRoleDao) {
		this.sysRoleDao = sysRoleDao;
	}

	public ResourceAssociationDao getResourceAssociationDao() {
		return resourceAssociationDao;
	}

	public void setResourceAssociationDao(
			ResourceAssociationDao resourceAssocaitionDao) {
		this.resourceAssociationDao = resourceAssocaitionDao;
	}




}